﻿using System;
using System.Collections.Generic;
using System.Drawing;

using MathNet.Numerics.LinearAlgebra;

namespace GridRayTracer
{
  [Serializable]
  public class Scene
  {
    public void Add(SceneObject sceneObject) 
    {
      objects.Add(sceneObject);
    }    
    
    /// <summary>
    /// Performs hit test for the whole scene.
    /// </summary>
    /// <param name="ray">Ray to intersect.</param>
    /// <returns>
    /// The nearest hit information, null if there is no intersection.
    /// </returns>
    public HitResult HitTest(Ray ray) 
    {
      HitResult nearestHit = null;
      var minDistanceSq = double.PositiveInfinity;
      
      foreach (var sceneObject in objects)
      {
        var hit = sceneObject.HitTest(ray);
        if (hit != null)
        {
          var distanceSq = (ray.Start - hit.HitPoint).SquaredNorm();
          if (distanceSq < minDistanceSq)
          {
            nearestHit = hit;
            minDistanceSq = distanceSq;
          }
        }
      }          
      
      return nearestHit;
    }
    
    public void Add(Light light) 
    {
      lights.Add(light);
    }    
    
    public Color GetLightAt(Vector point, Vector normal)
    {
      int red = 0;
      int green = 0;
      int blue = 0;
      
      foreach (var light in lights)
      {
        var dir = (light.Location - point).Normalize();
        var coef = Math.Max(0, dir.ScalarMultiply(normal));
        var color = light.GetColorAt(point);
        red += (int)(color.R * coef);
        green += (int)(color.G * coef);
        blue += (int)(color.B * coef);
      }
      
      return Color.FromArgb(Math.Min(255, red), Math.Min(255, green), Math.Min(255, blue));
    }
    
    List<SceneObject> objects = new List<SceneObject>();
    
    List<Light> lights = new List<Light>();
  }
}
